package com.phantom.irpc.framework.core.proxy.jdk;

import com.phantom.irpc.framework.core.common.RpcInvocation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

import static com.phantom.irpc.framework.core.common.cache.CommonClientCache.RESP_MAP;
import static com.phantom.irpc.framework.core.common.cache.CommonClientCache.SEND_QUEUE;

/**
 * JDK代理处理器
 * 各种代理工厂统一使用这个InvocationHandler
 * 核心任务：将需要调用的方法名称、服务名称、参数统统都封装好到RpcInvocation中，然后塞入到队列里，并且等待服务端的数据返回
 */
public class JDKClientInvocationHandler implements InvocationHandler {

    private final static Object OBJECT = new Object();

    private Class<?> clazz;

    public JDKClientInvocationHandler(Class<?> clazz) {
        this.clazz = clazz;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        RpcInvocation rpcInvocation = new RpcInvocation();
        rpcInvocation.setArgs(args);
        rpcInvocation.setTargetMethod(method.getName());
        rpcInvocation.setTargetServiceName(clazz.getName());
        // 这里注入了一个uuid，对每一次请求都做区分
        rpcInvocation.setUuid(UUID.randomUUID().toString());
        RESP_MAP.put(rpcInvocation.getUuid(), OBJECT);
        SEND_QUEUE.add(rpcInvocation);

        long beginTime = System.currentTimeMillis();
        // 客户端请求超时的一个判断依据
        while (System.currentTimeMillis() - beginTime < 3 * 1000) {
            Object obj = RESP_MAP.get(rpcInvocation.getUuid());
            if (obj instanceof RpcInvocation) {
                return ((RpcInvocation) obj).getResponse();
            }
        }

        throw new TimeoutException("client wait server's response timeout!");
    }
}
